package tmts;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import tmts.helpers.Encryption;

public class BroadCastService extends Thread
{

    private static final int BROADCAST_PORT = 1400;
    private static final long BROADCAST_DELAY = 2 * 1000;//2 sec delay
    protected static final String BROADCAST_MESSAGE = "TMTS_SERVER";
    private DatagramSocket datagramSocket;
    private byte[] sendData;
    private DatagramPacket broadCastPacket;
    private Enumeration<NetworkInterface> interfaces;
    private Runnable responseListener;

    public BroadCastService()
    {
        try
        {
            datagramSocket = new DatagramSocket();
            datagramSocket.setBroadcast(true);
            responseListener = new BroadCastResponseListener(datagramSocket);
            
            Thread responseThread = new Thread(responseListener);
            responseThread.start();

            try
            {
                sendData = Encryption.encrypt(BROADCAST_MESSAGE).getBytes();
            } catch (InvalidKeyException e)
            {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
            } catch (NoSuchPaddingException e)
            {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e)
            {
                e.printStackTrace();
            } catch (BadPaddingException e)
            {
                e.printStackTrace();
            }

            broadCastPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("255.255.255.255"), BROADCAST_PORT);
        } catch (SocketException e)
        {
            e.printStackTrace();
        } catch (UnknownHostException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void run()
    {
        while (true)
        {
            try
            {
                Server.debug("Sending broadcast message");
                broadCastPacket.setAddress(InetAddress.getByName("255.255.255.255"));
                datagramSocket.send(broadCastPacket);
                sendToWholeNetwork();
                Thread.sleep(BROADCAST_DELAY);
            } catch (UnknownHostException e)
            {
                e.printStackTrace();
            } catch (IOException e)
            {
                e.printStackTrace();
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }

    private void sendToWholeNetwork() throws IOException
    {
        interfaces = NetworkInterface.getNetworkInterfaces();

        while (interfaces.hasMoreElements())
        {
            NetworkInterface networkInterface = interfaces.nextElement();

            if (networkInterface.isLoopback() || !networkInterface.isUp())
                continue; // Don't want to broadcast to the loopback/down interfaces

            for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses())
            {
                InetAddress broadcast = interfaceAddress.getBroadcast();

                if (broadcast == null)
                    continue;

                if (broadcast.toString().equals("/0.0.0.0"))
                    continue;

                // Send the broadcast package
                broadCastPacket.setAddress(broadcast);
                datagramSocket.send(broadCastPacket);
            }
        }
    }
}